﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Kokomo.Mirror.Ia32
{
	public struct ModRM
	{
		public ModRM(byte value)
			: this()
		{
			this.Value = value;
		}

		public static ModRM FromNnn(byte nnn)
		{
			return new ModRM((byte)(nnn << 3));
		}

		public static ModRM FromModRMNnn(
			int mod,
			int rm,
			int nnn
			)
		{
			int value =
				(rm & 0x7)
				| ((nnn & 0x7) << 3)
				| ((mod) << 6)
				;

			return new ModRM((byte)value);
		}

		public override bool Equals(object obj)
		{
			if (!(obj is ModRM)) return false;

			ModRM other = (ModRM)obj;
			bool areEqual = (other.Value == this.Value);
			return areEqual;
		}

		public override int GetHashCode()
		{
			return this.Value;
		}

		public override string ToString()
		{
			return string.Format("{0:X2}, mod={1}, RM={2:x}, reg={3:x}",
				this.Value,
				this.Mod,
				this.RM,
				this.Reg
				);
		}

		public byte Value { get; private set; }

		public Mod Mod { get { return (Mod)((this.Value & 0xC0) >> 6); } }
		public int RM { get { return (this.Value & 0x7); } }
		public int Reg { get { return (this.Value & 0x38) >> 3; } }

		public AddressingForm16 AddressingForm16 { get { return (AddressingForm16)this.RM; } }
		public AddressingForm32 AddressingForm32
		{
			get
			{
				return (AddressingForm32)this.RM;
			}
		}

		public bool IndicatesDisp32
		{
			get
			{
				return (this.Mod == Ia32.Mod.None && this.RM == 5);
			}
		}

		public bool IndicatesSib
		{
			get
			{
				return
					(this.Mod != Ia32.Mod.reg)
					&& (this.AddressingForm32 == Ia32.AddressingForm32.Sib)
					;
			}
		}
	}
}
